package com.zijidelu.luframework.plugins.tomlock.core.handler.impl;

import com.zijidelu.luframework.utils.spring.beans.register.SpringSimpleBeanUtil;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockHandlerData;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockResult;
import com.zijidelu.luframework.plugins.tomlock.core.handler.BaseTomLockHandler;
import com.zijidelu.luframework.plugins.tomlock.core.handler.CalcHandlerLockHandler;
import com.zijidelu.luframework.plugins.tomlock.core.utils.TomLockSpELUtil;
import com.zijidelu.luframework.plugins.tomlock.core.utils.TomLockUtil;
import com.zijidelu.luframework.plugins.tomlock.redisson.RedissonLockExecutor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.function.Supplier;

/**
 * 处理计算处理器模式实现类。
 *
 * @author ZIJIDELU
 * @datetime 2025/4/13 19:13
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class CalcHandlerLockHandlerImpl implements CalcHandlerLockHandler {

    private final RedissonLockExecutor redissonLockExecutor;

    @Override
    public <T> T run(TomLockHandlerData tomLockData, Supplier<T> supplier) {
        // 校验参数
        tomLockData.validParams();

        // 构建SpEL表达式解析器
        final ExpressionParser spelExpressionParser = new SpelExpressionParser();

        // 初始化SpEL表达式上下文
        final StandardEvaluationContext standardEvaluationContext = TomLockSpELUtil.initEvaluationContext(tomLockData.getMethodParamsList());

        // 计算方法参数列表
        final List<Object> methodParamList = TomLockSpELUtil.calcMethodParamList(tomLockData.getParamExpression(), spelExpressionParser, standardEvaluationContext);

        final BaseTomLockHandler handlerBean = getBaseTomLockHandler(tomLockData);

        // 处理器计算方法获取锁KEY数据
        final TomLockResult tomLockResult = handlerBean.calcLock(methodParamList.toArray());
        tomLockResult.getResultList()
                .forEach(result -> result.setUniqueKey(TomLockUtil.calcDistributedLockKey(result.getUniqueKey())));

        return redissonLockExecutor.calcLockRun(tomLockData, tomLockResult, supplier);

    }

    /**
     * 查找锁处理器BEAN
     *
     * @param tomLockData 锁数据
     * @return BEAN
     */
    private static BaseTomLockHandler getBaseTomLockHandler(TomLockHandlerData tomLockData) {
        return SpringSimpleBeanUtil.getBean(tomLockData.getHandlerClass());
    }


}
